<?php

namespace app\services;

use app\models\Images;
use app\services\base\BaseService;
use app\exception\MyException;
use Imagine\Image\ManipulatorInterface;
use yii\imagine\Image;

class Upload
{
    use BaseService;

    // 允许上传的文件类型
    protected static $allow_file_type = [
        'jpg',
        'jpeg',
        'png',
        'gif',
        'bmp',
        'svg',
        'xls',
        'xlsx',
    ];

    protected static $dev_dir = 'uploads-development-001';


    public static function uploadImage($bucket = '', $env = '')
    {
        try {
            
            // empty
            if (!$_FILES || !$_FILES['file']) {
                throw new MyException('请上传文件');
            }

            // file extend
            $file_name = $_FILES['file']['name'];
            $file_extend = explode('.', $file_name);
            $file_extend = strtolower(end($file_extend));
            if (!in_array($file_extend, self::$allow_file_type)) {
                throw new MyException('文件类型错误');
            }
            
            // upload
            $result = self::upload($file_name, $_FILES['file']['tmp_name'], $bucket, $env);
            if (!$result) {
                throw new MyException('上传失败,文件太大或者路径错误');
            }

            return $result;
            
        } catch (MyException $e) {
            self::addError($e->getInfo());
            return false;
        }
    }

    protected static function upload($file_name, $file_path, $bucket = '', $env = '')
    {
        // file name
        $hash_key = md5(file_get_contents($file_path)) . '-' . time();
        $file_extend = explode('.', $file_name);
        $file_extend = strtolower(end($file_extend));

        // upload dir
        if ($env == 'development') {
            $upload_dir_path = \Yii::$app->getBasePath(). '/web/'. self::$dev_dir .'/' . $bucket. '/';
        } else {
            $upload_dir_path = \Yii::$app->getBasePath(). '/web/uploads/' . $bucket. '/';
        }

        $folder_name = date('Ymd');
        $upload_dir = $upload_dir_path . $folder_name;
        if (!file_exists($upload_dir)) {
            mkdir($upload_dir, 0777, true);
            chmod($upload_dir, 0777);
        }

        // upload
        $full_name = $folder_name . '/' . $hash_key . '.' . $file_extend;
        if (is_uploaded_file($file_path)) {
            move_uploaded_file($file_path, $upload_dir_path . $full_name);
        } else {
            file_put_contents($upload_dir_path . $full_name, file_get_contents($file_path));
        }

        // prefix
        if ($env == 'development') {
            $prefix = '/'.self::$dev_dir.'/' . ($bucket != '' ? $bucket . '/' : '');
        } else {
            $prefix = '/uploads/' . ($bucket != '' ? $bucket . '/' : '');
        }

        $thumbnail_name = '';
        $width = intval(\Yii::$app->request->get('width', -1));
        $height = intval(\Yii::$app->request->get('height', -1));
        $quality = intval(\Yii::$app->request->get('quality', 100));

        // save source
        // $source = $folder_name . '/' . $hash_key . '-source.' . $file_extend;
        // copy($upload_dir_path . $full_name, $upload_dir_path . $source);

        // watermark
        // $watermark = \Yii::$app->getBasePath() . '/web/miyi-watermark.png';
        // Image::watermark(
        //     $upload_dir_path . $full_name,
        //     $watermark,
        //     [10, 10]
        // )->save($upload_dir_path . $full_name);

        if ($quality < 100 && in_array($file_extend, ['jpg', 'jpeg', 'png'])) {

            // 获取原图片尺寸
            // list($w, $h) = getimagesize($upload_dir_path . $full_name);
            // Image::thumbnail(
            //     $upload_dir_path . $full_name,
            //     $w - 1,
            //     $h - 1
            // )->save($upload_dir_path . $full_name, ['png_compression_level' => 9]);


            $q = ['quality' => $quality];
            if ($file_extend == 'jpg' || $file_extend == 'jpeg') {
                // from 0 to 100
                $q = ['jpeg_quality' => $quality];
            }
            if ($file_extend == 'png') {
                // from 0 to 9
                // $q = ['png_compression_level' => 10 - (int)($quality / 10)];
                $q = ['png_compression_level' => (int)($quality / 10)];
            }

            // todo
            // ========================================================
            // 目前jpg压缩没有问题
            // 但是PNG压缩效果不佳
            // 还没有在linux上面测试,
            // 需要先安装扩展,再修改此处理上下文代码
            // =========================================================
            // 需要安装imagick库
            // $imagine = new Imagine();
            // $imagine->open($upload_dir_path . $full_name)
            //     ->save($upload_dir_path . $full_name, $q);
        }

        // jpg 1 - 100
        // png 0 - 9
        // 暂时关闭压缩
        $q = $quality;
        if ($file_extend == 'jpg' || $file_extend == 'jpeg') {
            // from 0 to 100
            // $q = $quality;
            $q = 100;
        }
        if ($file_extend == 'png') {
            // $q = (int)($quality / 10);
            $q = 10;
        }

        // max width
        $maxWidth = intval(\Yii::$app->request->get('max-width', -1));
        if ($maxWidth > -1 && in_array($file_extend, ['jpg', 'jpeg', 'png', 'bmp', 'gif'])) {
            list($o_w, $o_h) = getimagesize($upload_dir_path . $full_name);
            list($w, $h) = self::scaleByWidth($o_w, $o_h, $maxWidth);
            Image::thumbnail(
                $upload_dir_path . $full_name,
                $w,
                $h
            )->save($upload_dir_path . $full_name, ['quality' => $q]);
        }

        // thumbnail
        if ($width > -1 && in_array($file_extend, ['jpg', 'jpeg', 'png', 'bmp', 'gif'])) {
        // if ($width > -1 && $height > -1 && in_array($file_extend, ['jpg', 'jpeg', 'png', 'bmp', 'gif'])) {

            // 原来 的高度
            list($o_w, $o_h) = getimagesize($upload_dir_path . $full_name);
            list($w, $h) = self::scaleByWidth($o_w, $o_h, $width);
            $height = $h;

            $thumbnail_name = $folder_name . '/' . $hash_key . '-thumb.' . $file_extend;
            $result = Image::thumbnail(
                $upload_dir_path . $full_name,
                $width,
                $height,
                // ManipulatorInterface::THUMBNAIL_OUTBOUND     // 裁剪模式
                ManipulatorInterface::THUMBNAIL_INSET   // 填充模式
            )->save($upload_dir_path . $thumbnail_name, ['quality' => $q]);

            if (!$result) {
                return false;
            }
        }

        // save to db
        $model = new Images();
        $model->path = $prefix . $full_name;
        $model->thumbnail_path = $thumbnail_name ? $prefix . $thumbnail_name : '';
        $model->bucket = $bucket;
        if (!$model->save()) {
            return false;
        }

        return [
            'name' => $full_name,
            'prefix' => $prefix,
            'full_name' => $prefix . $full_name,
            'thumbnail' => $model->thumbnail_path,
            'bucket' => $bucket,
            // db image id
            'id' => $model->id,
        ];
    }

    /**
     * max width
     *
     * @param $width
     * @param $height
     * @param int $max
     * @return array
     */
    public static function scaleByWidth($width, $height, $max = 1125)
    {
        if ($width >= $max) {
            $ratio = $max / $width;
            $width = $max;
            $height = round($height * $ratio);
        }

        return [$width, $height];
    }
}